package com.zj.easywebview

import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import com.zj.easywebview.JsBridge.register
import com.zj.easywebview.JsBridge.callJava
import android.os.Build
import com.google.android.material.internal.ContextUtils
import android.text.TextUtils
import android.util.AttributeSet
import android.util.Log
import android.webkit.*
import com.zj.easywebview.util.CommonUtil
import java.io.IOException
import java.lang.Exception
import java.net.URLEncoder
import java.util.HashMap

/**
 * Created by xievxin on 2017/11/9.
 */
class RealEasyWebview(context: Context, attrs: AttributeSet?) : EasyWebview(context, attrs) {

    override fun onInit() {
        webView?.setLayerType(LAYER_TYPE_HARDWARE, null) // 公司二手华为P9不支持高性能css
        setWebCfg()
        addJavaScript()
    }

    private fun setWebCfg() {
        webView?.let {
            val webSettings = it.settings
            val userAgentString = webSettings.userAgentString
            //重新设置UserAgent，便于h5判断是否在本app中打开的
            webSettings.userAgentString = "$userAgentString;android/ckjrFund"
            webSettings.textZoom = 100
            webSettings.blockNetworkImage = true
            webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH)
            webSettings.javaScriptEnabled = true
            webSettings.domStorageEnabled = true
            webSettings.setAppCacheEnabled(true)
            webSettings.databaseEnabled = true
            webSettings.savePassword = false
            webSettings.cacheMode = WebSettings.LOAD_NO_CACHE

            // 在安卓5.0之后，默认不允许加载http与https混合内容，需要设置webview允许其加载混合网络协议内容
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
            }
            if (Build.VERSION.SDK_INT < 19) {
                // 先加载完页面再loading图片
                // 4.4以上在onPageFinished时再恢复图片加载时,如果存在多张图片引用的是相同的src时，会只有一个image标签得到加载
                it.settings.loadsImagesAutomatically = false
            }
        }
    }

    private fun addJavaScript() {
        register("nativeJsImpl", NativeJsImpl::class.java)
        //addJavascriptInterface(new JsFunctions(context), "js");
    }

    fun postUrl(url: String?, values: Map<String, Any>?) {
        var data = ""
        if (values != null && values.size > 0) {
            for (key in values.keys) {
                data = data + "&" + key + "=" + URLEncoder.encode(values[key].toString())
            }
        }
        super.postUrl(url, data.replaceFirst("&".toRegex(), "").toByteArray())
    }

    val url: String?
        get() = webView?.url

    override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
        return false
    }

    override fun shouldInterceptRequest(webView: WebView?, url: String?): WebResourceResponse? {
        Log.i(TAG, "shouldInterceptRequest: $url")
        if (!TextUtils.isEmpty(url)) {
            // 有本地资源就别去下载
            val response = getLocalWebSource(url)
            if (response != null) {
                return response
            }
        }
        return super.shouldInterceptRequest(webView, url)
    }

    override fun onJsAlert(
        view: WebView?,
        url: String?,
        message: String?,
        result: JsResult?
    ): Boolean {
        CommonUtil.dialogTip(
            context, message, context.getString(R.string.sure),
            { _, _ -> result!!.confirm() }, null
        )?.setCancelable(false)
        return true
    }

    override fun onJsConfirm(
        view: WebView?,
        url: String?,
        message: String?,
        result: JsResult?
    ): Boolean {
        val dlg = AlertDialog.Builder(context)
            .setTitle("提示")
            .setMessage(message)
            .setPositiveButton(context.getString(R.string.sure)) { _, _ -> result!!.confirm() }
            .setNegativeButton(context.getString(R.string.cancel)) { _, _ -> result!!.cancel() }
            .create()
        dlg.setCancelable(false)
        dlg.show()
        return true
    }

    override fun onJsPrompt(
        view: WebView?,
        url: String?,
        message: String?,
        defaultValue: String?,
        result: JsPromptResult?
    ): Boolean {
        try {
            //js调用Android方法
            callJava(context, view!!, message)
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            result!!.confirm()
        }
        return true
    }

    override fun onPageFinished(view: WebView?, url: String?) {
        webView?.apply {
            settings.blockNetworkImage = false
            if (!settings.loadsImagesAutomatically) {
                settings.loadsImagesAutomatically = true
            }
        }
    }

    /**
     * shouldInterceptRequest返回本地资源
     *
     * @param url
     * @return
     */
    private fun getLocalWebSource(url: String?): WebResourceResponse? {
        val fileName = getLocalResourceName(url)
        if (TextUtils.isEmpty(fileName)) {
            return null
        }
        var response: WebResourceResponse? = null
        try {
            val `is` = context.assets.open("websources/$fileName")
            response = WebResourceResponse(getMimeType(fileName), "utf-8", `is`)
            Log.i(TAG, "getLocalWebSource: $fileName loaded local!!!")
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return response
    }

    /**
     * websources
     *
     * @param url webRequest
     * @return 本地文件名 null则表示不存在
     */
    private fun getLocalResourceName(url: String?): String? {
        var key: String? = null
        val it = localSourceMap.keys.iterator()
        while (it.hasNext()) {
            key = it.next()
            if (url!!.endsWith(key)) {
                return key
            }
        }
        return null
    }

    /**
     * mimeType 从 mime.types文件中查
     *
     * @param fileName
     * @return
     */
    private fun getMimeType(fileName: String?): String? {
        if (fileName!!.endsWith("js")) {
            return "application/x-javascript"
        } else if (fileName.endsWith("css")) {
            return "text/css"
        }
        return null
    }

    override fun onReceivedTitle(view: WebView?, title: String?) {
        super.onReceivedTitle(view, title)
    }


    companion object {
        private const val TAG = "RealEasyWebview"
        private val localSourceMap: Map<String, Any> = HashMap()
    }
}